package cz.muni.fi.pa165.languageschool.rest;

import cz.muni.fi.pa165.languageschool.DataFetchException;
import cz.muni.fi.pa165.languageschool.dto.CourseTO;
import cz.muni.fi.pa165.languageschool.service.CourseService;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import javax.ejb.Singleton;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.UriInfo;
import javax.ws.rs.PathParam;
import javax.ws.rs.Path;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

/**
 * REST courses resource
 *
 * @author Michal Fucik (3956224) michal.fuca.fucik(at)gmail.com
 */
@Component
@Path("/courses")
@Singleton
public class CoursesResource {

    private CourseService courseService;
    final static Logger log = LoggerFactory.getLogger(CourseResource.class);
    @Context
    private UriInfo context;

    public void setCourseService(CourseService courseService) {
        this.courseService = courseService;
    }

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public String getPlain() {
        StringBuilder res = new StringBuilder();
        try {
            if (courseService == null) {
                throw new WebApplicationException(Response.Status.NO_CONTENT);
            }

            for (CourseTO cto : courseService.getAllCourses()) {
                res.append(cto.toString());
                res.append(",");
            }
        } catch (DataFetchException | NullPointerException x) {
            log.error(x.getMessage(), x);
            throw new WebApplicationException(Response.Status.NOT_FOUND);
        }

        return res.toString();
    }

    @GET
    @Path("{json}")
    @Produces(MediaType.APPLICATION_JSON)
    public List<CourseResource> getAll() {
        List<CourseResource> list = new ArrayList<>();
        try {
            if (courseService == null) {
                throw new WebApplicationException(Response.Status.NO_CONTENT);
            }

            for (CourseTO cto : courseService.getAllCourses()) {
                list.add(new CourseResource(cto));
            }
        } catch (DataFetchException | NullPointerException x) {
            log.error(x.getMessage(), x);
            throw new WebApplicationException(Response.Status.NOT_FOUND);
        }
        return list;
    }

    @Path("{id}")
    public CourseResource getCourseResource(@PathParam("id") Integer id) {
        CourseTO cto = null;
        CourseResource crs = null;
        try {
            if (courseService == null) {
                throw new WebApplicationException(Response.Status.NO_CONTENT);
            }
            cto = courseService.getCourse(new Long(id));
            crs = new CourseResource(cto);
            System.out.println();
            System.out.println("CoursesResource getCourseResource id " + id + "    " + cto);
            System.out.println();
        } catch (DataFetchException | NullPointerException x) {
            log.error(x.getMessage(), x);
            x.printStackTrace(System.out);
            throw new WebApplicationException(Response.Status.NOT_FOUND);
        }
        return crs;
    }

    @GET
    @Path("json/{id}")
    @Produces({MediaType.APPLICATION_JSON})
    public CourseResource getCourse(@PathParam("id") Integer id) {
        CourseTO cto = null;
        CourseResource crs = null;
        try {
            if (courseService == null) {
                throw new WebApplicationException(Response.Status.NO_CONTENT);
            }
            cto = courseService.getCourse(new Long(id));
            if (cto == null) {
                throw new WebApplicationException(Response.Status.NOT_FOUND);
            }
            crs = new CourseResource(cto);

        } catch (DataFetchException | NullPointerException x) {
            log.error(x.getMessage(), x);
            x.printStackTrace(System.out);
            throw new WebApplicationException(Response.Status.NOT_FOUND);
        }
        return crs;
    }

    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    public Response createCourse(CourseResource courseResource) {
        try {
            if (courseService == null) {
                throw new WebApplicationException(Response.Status.NO_CONTENT);
            }
            courseResource.setId(null);
            courseService.createCourse((CourseTO) courseResource);
        } catch (DataFetchException | NullPointerException x) {
            log.error(x.getMessage(), x);
            x.printStackTrace(System.out);
            throw new WebApplicationException(Response.Status.BAD_REQUEST);
        }
        log.info("Course created id=" + courseResource.getId());
        return Response.created(URI.create(context.getAbsolutePath() + "/" + courseResource.getId())).build();
    }

    @PUT
    @Consumes(MediaType.APPLICATION_JSON)
    public Response updateCourse(CourseResource courseResource) {
        try {
            if (courseService == null) {
                throw new WebApplicationException(Response.Status.NO_CONTENT);
            }
            courseService.updateCourse((CourseTO) courseResource);
        } catch (DataFetchException | NullPointerException x) {
            log.error(x.getMessage(), x);
            x.printStackTrace(System.out);
            throw new WebApplicationException(Response.Status.NOT_FOUND);
        }
        log.info("Course updated to = " + courseService.toString());
        return Response.created(URI.create(context.getAbsolutePath() + "json/" + courseResource.getId())).build();
    }

    @DELETE
    @Path("{id}")
    public Response deleteCourse(@PathParam("id") Integer id) {
        CourseTO cto = new CourseTO();
        cto.setId(new Long(id));
        try {
            if (courseService == null) {
                throw new WebApplicationException(Response.Status.NO_CONTENT);
            }
            courseService.deleteCourse(cto);
        } catch (DataFetchException | NullPointerException x) {
            log.error(x.getMessage(), x);
            x.printStackTrace(System.out);
            throw new WebApplicationException(Response.Status.NOT_FOUND);
        }
        log.info("Course deleted id = " + id);
        return Response.status(Response.Status.OK).build();
    }
}
